"""
Python高级特性学习 - 类型注解
====================

本文件演示了Python中类型注解的使用方法，包括基本类型、集合类型、函数类型、泛型等。
类型注解用于提高代码的可读性和可维护性，帮助IDE提供更好的代码补全和错误检查。
Python 3.5+开始支持类型注解，通过typing模块提供丰富的类型提示功能。
"""

from typing import List, Dict, Tuple, Set, Optional, Union, Any, Callable, TypeVar, Generic, Protocol, TypedDict, \
    NamedTuple, overload
from dataclasses import dataclass
import asyncio


# 1. 基本类型注解
# ----------------

def greet(name: str) -> str:
    """问候函数 - 演示基本类型注解

    Args:
        name (str): 姓名

    Returns:
        str: 问候语
    """
    return f"Hello, {name}!"


def calculate_area(length: float, width: float) -> float:
    """计算矩形面积

    Args:
        length (float): 长度
        width (float): 宽度

    Returns:
        float: 面积
    """
    return length * width


# 2. 集合类型注解
# ----------------

def process_numbers(numbers: List[int]) -> Dict[str, int]:
    """处理数字列表 - 演示集合类型注解

    Args:
        numbers (List[int]): 数字列表

    Returns:
        Dict[str, int]: 包含统计信息的字典
    """
    return {
        "count": len(numbers),
        "sum": sum(numbers),
        "max": max(numbers),
        "min": min(numbers)
    }


def get_coordinates() -> Tuple[float, float]:
    """获取坐标 - 演示元组类型注解

    Returns:
        Tuple[float, float]: 坐标元组 (x, y)
    """
    return (10.5, 20.3)


def unique_words(text: str) -> Set[str]:
    """获取文本中的唯一单词

    Args:
        text (str): 输入文本

    Returns:
        Set[str]: 唯一单词集合
    """
    return set(text.lower().split())


# 3. 可选类型和联合类型
# ----------------------

def find_user(user_id: int) -> Optional[str]:
    """查找用户 - 演示可选类型

    Args:
        user_id (int): 用户ID

    Returns:
        Optional[str]: 用户名，如果未找到则返回None
    """
    users = {1: "Alice", 2: "Bob", 3: "Charlie"}
    return users.get(user_id)


def format_id(user_id: Union[int, str]) -> str:
    """格式化用户ID - 演示联合类型

    Args:
        user_id (Union[int, str]): 用户ID，可以是整数或字符串

    Returns:
        str: 格式化后的用户ID
    """
    return f"ID-{user_id}"


# 4. 函数类型注解
# ----------------

def apply_operation(numbers: List[int], operation: Callable[[int], int]) -> List[int]:
    """应用操作到数字列表 - 演示函数类型注解

    Args:
        numbers (List[int]): 数字列表
        operation (Callable[[int], int]): 操作函数

    Returns:
        List[int]: 处理后的数字列表
    """
    return [operation(num) for num in numbers]


def square(x: int) -> int:
    """计算平方

    Args:
        x (int): 输入数字

    Returns:
        int: 平方值
    """
    return x * x


# 5. 泛型和自定义泛型类
# ----------------------

T = TypeVar('T')


class Stack(Generic[T]):
    """泛型栈类 - 演示泛型的使用

    泛型允许我们在定义类或函数时使用类型变量，
    在使用时再指定具体的类型，提高代码的复用性。
    """

    def __init__(self) -> None:
        """初始化空栈"""
        self._items: List[T] = []

    def push(self, item: T) -> None:
        """入栈

        Args:
            item (T): 要入栈的元素
        """
        self._items.append(item)

    def pop(self) -> T:
        """出栈

        Returns:
            T: 栈顶元素

        Raises:
            IndexError: 当栈为空时
        """
        if not self._items:
            raise IndexError("pop from empty stack")
        return self._items.pop()

    def is_empty(self) -> bool:
        """检查栈是否为空

        Returns:
            bool: 如果栈为空返回True，否则返回False
        """
        return len(self._items) == 0

    def size(self) -> int:
        """获取栈大小

        Returns:
            int: 栈中元素的数量
        """
        return len(self._items)


# 6. 协议（Protocol）
# -------------------

class Drawable(Protocol):
    """可绘制对象协议 - 演示Protocol的使用

    Protocol用于定义接口，不关心具体实现，只关心对象是否有特定的方法。
    这是一种鸭子类型的概念：如果它走起来像鸭子，叫起来像鸭子，那它就是鸭子。
    """

    def draw(self) -> None:
        """绘制方法"""
        ...

    def area(self) -> float:
        """计算面积方法

        Returns:
            float: 面积
        """
        ...


class Circle:
    """圆形类 - 实现Drawable协议"""

    def __init__(self, radius: float) -> None:
        """初始化圆形

        Args:
            radius (float): 半径
        """
        self.radius = radius

    def draw(self) -> None:
        """绘制圆形"""
        print(f"绘制半径为 {self.radius} 的圆形")

    def area(self) -> float:
        """计算圆形面积

        Returns:
            float: 圆形面积
        """
        return 3.14159 * self.radius ** 2


class Rectangle:
    """矩形类 - 实现Drawable协议"""

    def __init__(self, width: float, height: float) -> None:
        """初始化矩形

        Args:
            width (float): 宽度
            height (float): 高度
        """
        self.width = width
        self.height = height

    def draw(self) -> None:
        """绘制矩形"""
        print(f"绘制 {self.width}x{self.height} 的矩形")

    def area(self) -> float:
        """计算矩形面积

        Returns:
            float: 矩形面积
        """
        return self.width * self.height


def render_shape(shape: Drawable) -> None:
    """渲染形状 - 演示Protocol的使用

    Args:
        shape (Drawable): 可绘制的形状对象
    """
    shape.draw()
    print(f"面积: {shape.area():.2f}")


# 7. TypedDict
# ------------

class Person(TypedDict):
    """人员信息字典类型 - 演示TypedDict的使用

    TypedDict用于定义具有特定键和值类型的字典结构，
    提供比普通Dict更精确的类型检查。
    """
    name: str
    age: int
    email: str


class Employee(Person):
    """员工信息字典类型 - 继承Person

    可以通过继承扩展TypedDict，添加新的字段。
    """
    employee_id: int
    department: str


def print_person_info(person: Person) -> None:
    """打印人员信息

    Args:
        person (Person): 人员信息字典
    """
    print(f"姓名: {person['name']}")
    print(f"年龄: {person['age']}")
    print(f"邮箱: {person['email']}")


def print_employee_info(employee: Employee) -> None:
    """打印员工信息

    Args:
        employee (Employee): 员工信息字典
    """
    print_person_info(employee)  # Employee继承自Person，可以传入
    print(f"员工ID: {employee['employee_id']}")
    print(f"部门: {employee['department']}")


# 8. 命名元组
# ------------

class Point(NamedTuple):
    """点坐标命名元组 - 演示NamedTuple的使用

    NamedTuple用于创建具有命名字段的不可变元组，
    比普通元组更易读，比类更轻量。
    """
    x: float
    y: float

    def distance_from_origin(self) -> float:
        """计算到原点的距离

        Returns:
            float: 到原点的距离
        """
        return (self.x ** 2 + self.y ** 2) ** 0.5


# 9. 数据类
# ----------

@dataclass
class Product:
    """产品数据类 - 演示dataclass的使用

    dataclass装饰器自动生成__init__、__repr__、__eq__等方法，
    减少样板代码，使类定义更简洁。
    """
    name: str
    price: float
    in_stock: bool = True

    def apply_discount(self, discount: float) -> float:
        """应用折扣

        Args:
            discount (float): 折扣率 (0-1)

        Returns:
            float: 折扣后价格
        """
        return self.price * (1 - discount)


# 10. 重载函数
# ------------

@overload
def process_input(data: str) -> int:
    ...


@overload
def process_input(data: int) -> str:
    ...


def process_input(data: Union[str, int]) -> Union[int, str]:
    """处理输入数据 - 演示函数重载

    根据输入类型返回不同类型的结果：
    - 输入字符串返回整数（字符串长度）
    - 输入整数返回字符串（整数的字符串表示）

    Args:
        data (Union[str, int]): 输入数据

    Returns:
        Union[int, str]: 处理结果
    """
    if isinstance(data, str):
        return len(data)
    else:
        return str(data)


# 11. 常量和类变量
# ------------------

from typing import ClassVar


class MathConstants:
    """数学常量类 - 演示常量和类变量

    使用ClassVar类型注解来标识类变量，
    这些变量属于类而不是实例。
    """
    PI: ClassVar[float] = 3.14159
    E: ClassVar[float] = 2.71828

    # 实例变量
    def __init__(self, multiplier: float = 1.0) -> None:
        """初始化

        Args:
            multiplier (float): 乘数
        """
        self.multiplier = multiplier

    def get_scaled_pi(self) -> float:
        """获取缩放后的PI值

        Returns:
            float: 缩放后的PI值
        """
        return self.PI * self.multiplier


# 12. 生成器和迭代器
# -------------------

from typing import Iterator, Generator


def count_up(limit: int) -> Iterator[int]:
    """向上计数迭代器

    Args:
        limit (int): 计数上限

    Yields:
        int: 计数值
    """
    for i in range(limit):
        yield i


def fibonacci_generator(n: int) -> Generator[int, None, None]:
    """斐波那契数列生成器

    Args:
        n (int): 生成数列的项数

    Yields:
        int: 斐波那契数列中的数字
    """
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b


# 13. 异步函数
# ------------

async def fetch_data(url: str) -> str:
    """获取数据 - 演示异步函数类型注解

    Args:
        url (str): URL地址

    Returns:
        str: 获取的数据
    """
    # 模拟异步操作
    await asyncio.sleep(0.1)
    return f"Data from {url}"


async def process_data_async(urls: List[str]) -> List[str]:
    """异步处理数据

    Args:
        urls (List[str]): URL列表

    Returns:
        List[str]: 处理结果列表
    """
    tasks = [fetch_data(url) for url in urls]
    results = await asyncio.gather(*tasks)
    return results


# 14. 类型别名
# ------------

from typing import List

# 定义类型别名，提高代码可读性
Vector = List[float]
Matrix = List[Vector]


def matrix_multiply(a: Matrix, b: Matrix) -> Matrix:
    """矩阵乘法 - 演示类型别名

    Args:
        a (Matrix): 第一个矩阵
        b (Matrix): 第二个矩阵

    Returns:
        Matrix: 乘积矩阵
    """
    # 简化的矩阵乘法实现
    result = []
    for i in range(len(a)):
        row = []
        for j in range(len(b[0])):
            sum_val = sum(a[i][k] * b[k][j] for k in range(len(b)))
            row.append(sum_val)
        result.append(row)
    return result


def type_annotation_examples() -> None:
    """类型注解示例函数 - 演示各种类型注解的使用"""
    print("=== 类型注解示例 ===")

    # 1. 基本类型
    greeting = greet("Alice")
    area = calculate_area(5.0, 3.0)
    print(f"问候语: {greeting}")
    print(f"面积: {area}")

    # 2. 集合类型
    numbers = [1, 2, 3, 4, 5]
    stats = process_numbers(numbers)
    print(f"数字统计: {stats}")

    coords = get_coordinates()
    print(f"坐标: {coords}")

    words = unique_words("hello world hello python")
    print(f"唯一单词: {words}")

    # 3. 可选类型和联合类型
    user = find_user(1)
    print(f"找到用户: {user}")

    formatted_id = format_id(123)
    print(f"格式化ID: {formatted_id}")

    # 4. 函数类型
    squared_numbers = apply_operation([1, 2, 3, 4], square)
    print(f"平方后: {squared_numbers}")

    # 5. 泛型
    stack: Stack[int] = Stack()
    stack.push(1)
    stack.push(2)
    stack.push(3)
    print(f"栈大小: {stack.size()}")
    print(f"出栈元素: {stack.pop()}")

    # 6. Protocol
    circle = Circle(5.0)
    rectangle = Rectangle(4.0, 6.0)
    render_shape(circle)
    render_shape(rectangle)

    # 7. TypedDict
    person: Person = {
        "name": "Alice",
        "age": 30,
        "email": "alice@example.com"
    }
    print_person_info(person)

    employee: Employee = {
        "name": "Bob",
        "age": 25,
        "email": "bob@example.com",
        "employee_id": 1001,
        "department": "Engineering"
    }
    print_employee_info(employee)

    # 8. 命名元组
    point = Point(3.0, 4.0)
    print(f"点坐标: ({point.x}, {point.y})")
    print(f"到原点距离: {point.distance_from_origin():.2f}")

    # 9. 数据类
    product = Product("笔记本电脑", 5999.99, True)
    print(f"产品: {product}")
    print(f"折扣价: {product.apply_discount(0.1):.2f}")

    # 10. 重载函数
    str_result = process_input("hello")
    int_result = process_input(123)
    print(f"字符串处理结果: {str_result}")
    print(f"整数处理结果: {int_result}")

    # 11. 常量和类变量
    math_const = MathConstants(2.0)
    print(f"PI值: {MathConstants.PI}")
    print(f"缩放后的PI: {math_const.get_scaled_pi()}")

    # 12. 生成器和迭代器
    print("向上计数:", list(count_up(5)))
    print("斐波那契数列:", list(fibonacci_generator(10)))

    # 14. 类型别名
    matrix_a: Matrix = [[1, 2], [3, 4]]
    matrix_b: Matrix = [[5, 6], [7, 8]]
    product_matrix = matrix_multiply(matrix_a, matrix_b)
    print(f"矩阵乘积: {product_matrix}")


async def async_examples() -> None:
    """异步示例函数"""
    print("\n=== 异步示例 ===")
    urls = ["http://example.com/1", "http://example.com/2", "http://example.com/3"]
    results = await process_data_async(urls)
    print(f"异步处理结果: {results}")


def main() -> None:
    """主函数 - 运行所有示例

    按顺序执行所有类型注解相关的示例函数，
    展示其概念、实现方式和优势。
    """
    print("Python类型注解学习示例\n" + "=" * 30)

    # 类型注解示例
    type_annotation_examples()

    # 异步示例
    asyncio.run(async_examples())

    print("\n所有示例执行完成！")


if __name__ == "__main__":
    main()